package com.wkc;

import java.util.Timer;
import java.util.TimerTask;
import android.app.Activity;
import android.media.AudioManager;
import android.media.MediaPlayer;
import android.media.MediaPlayer.OnBufferingUpdateListener;
import android.media.MediaPlayer.OnCompletionListener;
import android.media.MediaPlayer.OnErrorListener;
import android.media.MediaPlayer.OnPreparedListener;
import android.media.MediaPlayer.OnVideoSizeChangedListener;
import android.os.Build;
import android.os.Handler;
import android.os.Message;
import android.util.Log;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
import android.view.ViewGroup;

public class VideoPlayer implements 
		OnBufferingUpdateListener, 
        OnCompletionListener, 
        OnPreparedListener,
        OnVideoSizeChangedListener, 
        SurfaceHolder.Callback, 
        OnErrorListener 
{
    private static final String TAG = "VideoPlayer";
    private int mVideoWidth;
    private int mVideoHeight;
    private String videoUrl;
    private MediaPlayer mMediaPlayer;
    private SurfaceView surfaceView;
    private SurfaceHolder surfaceHolder;
    private boolean videoSizeValidate;
    private boolean mediaPreparing;
    private boolean mediaPrepared;
    private boolean surfaceCreated;
    private int lastPosition;

    private VideoPlayerInterface videoPlayerInterface;
	private Timer mTimer;
	private TimerTask mTimerTask;
	
	private Handler handler=new Handler() 
	{
		public void handleMessage(Message msg)
		{
			super.handleMessage(msg);
			
			switch(msg.what)
			{
				case 0:
					{
						if(videoPlayerInterface!=null)
						{
							videoPlayerInterface.onVideoPlayerError();
						}
					}
					break;
				case 1:
					{
						if(videoPlayerInterface!=null)
						{
							int position=msg.arg1;
							int duration=msg.arg2;
							videoPlayerInterface.onVideoPlayerPositionChanged(position,duration);
						}
					}
					break;
				case 2:
					{
						if(videoPlayerInterface!=null)
						{
							int percent=msg.arg1;
							videoPlayerInterface.onVideoPlayerBufferingUpdate(percent);
						}
					}
					break;
				case 3:
					{
						if(videoPlayerInterface!=null)
						{
							videoPlayerInterface.onVideoPlayerPrepared();
						}
					}
					break;
				case 4:
					{
						if(videoPlayerInterface!=null)
						{
							videoPlayerInterface.onVideoPlayerCompletion();
						}
					}
					break;
			}
		}
	};
    
	public VideoPlayer(SurfaceView surfaceView,VideoPlayerInterface videoPlayerInterface) 
    {
		this.videoPlayerInterface=videoPlayerInterface;
		this.surfaceView=surfaceView;
    }
	
	public void setVideoUrl(String videoUrl) 
	{
		this.videoUrl=videoUrl;
	}

    public boolean play() 
    {
    		boolean playedImmidiately=false;
    	
        if(surfaceHolder==null)
        {
	        surfaceHolder = surfaceView.getHolder();
	        surfaceHolder.setKeepScreenOn(true);
	        surfaceHolder.addCallback(this);
	        
	        if(Build.VERSION.SDK_INT < Build.VERSION_CODES.HONEYCOMB)
	        {
	            surfaceHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
	        }
        }
        else if(surfaceCreated)
        {
	        	if(mediaPrepared)
	    		{
	        		mMediaPlayer.start();
	        		startTimer();
	        		
	        		playedImmidiately=true;
	    		}
	        	else if(!mediaPreparing)
	        	{
	        		prepareMediaPlayer();
	        	}
        }
    		
    		return playedImmidiately;
    }
    
    private void prepareMediaPlayer()
    {	
    		if(videoUrl==null)
    		{
    			return;
    		}
    	
        try 
        {
	        	if(mMediaPlayer==null)
	        	{
	        		mMediaPlayer = new MediaPlayer();
	        	}
	        	else
	        	{
	        		mMediaPlayer.reset();
	        	}
	        	
            mMediaPlayer.setDataSource(videoUrl);
            mMediaPlayer.setDisplay(surfaceHolder);
            mMediaPlayer.setScreenOnWhilePlaying(true);
            mMediaPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC);
            
            mMediaPlayer.setOnBufferingUpdateListener(this);
            mMediaPlayer.setOnCompletionListener(this);
            mMediaPlayer.setOnPreparedListener(this);
            mMediaPlayer.setOnVideoSizeChangedListener(this);
            mMediaPlayer.setOnErrorListener(this);
            
            mMediaPlayer.prepareAsync();
            mediaPreparing=true;
        } 
        catch (Exception e) 
        {
            Log.e(TAG, "error: " + e.getMessage(), e);
        }
    }
    
    public boolean pause()
	{
    		if(!mediaPrepared)
    		{
    			return false;
    		}
    		
    		cancelTimer();
		if (mMediaPlayer != null) 
		{
			mMediaPlayer.pause();
			lastPosition=mMediaPlayer.getCurrentPosition();
		}
		
		return true;
	}
 
	public void stop()
	{
		cancelTimer();

		mVideoWidth=0;
        mVideoHeight=0;
        
        mediaPrepared=false;
        videoSizeValidate=false;
        
		if (mMediaPlayer != null) 
		{
			mMediaPlayer.stop();
			mMediaPlayer.release();
			mMediaPlayer = null;
        }
	}
	
	public void seekToPercent(float seekToPercent)
	{
		if (mMediaPlayer != null) 
		{
			int msec=(int) (seekToPercent*mMediaPlayer.getDuration());
			mMediaPlayer.seekTo(msec);
        }
	}
	
	public boolean isPlaying()
	{
		boolean playing=false;
		
		if (mMediaPlayer != null) 
		{
			playing=mMediaPlayer.isPlaying();
        }
		
		return playing;
	}
    
	//from SurfaceHolder.Callback
    public void surfaceCreated(SurfaceHolder holder) 
    {
        Log.d(TAG, "surfaceCreated");

        if(!surfaceCreated)
        {
        		surfaceCreated=true;
        	
        		if(mMediaPlayer==null)
        		{
        			prepareMediaPlayer();
        		}
        }
    }
    
    //from SurfaceHolder.Callback
    public void surfaceChanged(SurfaceHolder surfaceholder, int i, int j, int k) 
    {
        Log.d(TAG, "surfaceChanged");

        updatePlayeViewSize();
    }
    
    //from SurfaceHolder.Callback
    public void surfaceDestroyed(SurfaceHolder surfaceholder) 
    {
        Log.d(TAG, "surfaceDestroyed");
        surfaceCreated=false;
        mediaPrepared=false;
        videoSizeValidate=false;

//        if(mMediaPlayer!=null && mMediaPlayer.isPlaying())
//        {
//        		lastPosition = mMediaPlayer.getCurrentPosition();
//        }
    }
    
    //from OnPreparedListener
    public void onPrepared(MediaPlayer mediaplayer) 
    {
        Log.d(TAG, "onPrepared called");

        mediaPreparing=false;
        mediaPrepared=true;
        
        if (mediaPrepared && videoSizeValidate) 
        {
        		updatePlayeViewSize();
        		
            mMediaPlayer.start();
            if(lastPosition>0)
            {
            		mMediaPlayer.seekTo(lastPosition);
            		lastPosition=0;
            }
            startTimer();
            
            handler.sendEmptyMessage(3);
        }
    }
    
    @Override
	public boolean onError(MediaPlayer arg0, int arg1, int arg2) 
	{
    		Log.d(TAG, "onError");
    		mediaPreparing=false;
    		handler.sendEmptyMessage(0);

		return true;
	}
    
    //from OnBufferingUpdateListener
    public void onBufferingUpdate(MediaPlayer arg0, int percent) 
    {
        //Log.d(TAG, "onBufferingUpdate percent:" + percent);

        Message msg=new Message();
		msg.what=2;
		msg.arg1=percent;
		handler.sendMessage(msg);
    }
    
    //from OnVideoSizeChangedListener
    public void onVideoSizeChanged(MediaPlayer mp, int width, int height) 
    {
        Log.v(TAG, "onVideoSizeChanged width: " + width + "  height: " + height);
        
        if (width == 0 || height == 0) 
        {
            Log.e(TAG, "invalid video width(" + width + ") or height(" + height
                    + ")");
            return;
        }
        
        mVideoWidth=width;
        mVideoHeight=height;
        videoSizeValidate=true;

        if (mediaPrepared && videoSizeValidate) 
        {
        		updatePlayeViewSize();
            mMediaPlayer.start();
        }
    }

    //from OnCompletionListener
    public void onCompletion(MediaPlayer arg0) 
    {
        Log.d(TAG, "onCompletion called");
        
        mediaPrepared=false;
        mediaPreparing=false;
        cancelTimer();
        
        handler.sendEmptyMessage(4);
    }
    
    public void updatePlayeViewSize()
    {
    		Activity activity=(Activity)surfaceView.getContext();
    		int screenWidth = activity.getWindowManager().getDefaultDisplay().getWidth();
        int screenHeight = activity.getWindowManager().getDefaultDisplay().getHeight();
        
        int layoutWidth=screenWidth;
        int layoutHeight=screenHeight;
        
        //Log.i("getDefaultDisplay","screenWidth:"+screenWidth+" screenHeight:"+screenHeight);
        
        if(layoutHeight>layoutWidth)
        {
        		//Portrait 竖屏
        		layoutHeight=(int) (((float)mVideoHeight / (float)mVideoWidth) * (float)screenWidth);;
        }
        else
        {
        		//Landscape 横屏
        }
        
        surfaceHolder.setFixedSize(layoutWidth, layoutHeight);
        
        ViewGroup.LayoutParams lp = (ViewGroup.LayoutParams)surfaceView.getLayoutParams();
        lp.width = layoutWidth;
        lp.height = layoutHeight;
        surfaceView.setLayoutParams(lp);  
    }
    
    public void startTimer()
    {
    		mTimerTask = new TimerTask() 
    		{
	    		@Override
	    		public void run() 
	    		{
	    			if(mMediaPlayer==null)
	    				return;
	    			
	    			if (mMediaPlayer.isPlaying()) 
	    			{
	    				int position = mMediaPlayer.getCurrentPosition();
	    				int duration = mMediaPlayer.getDuration();
	    	 
	    				if (duration > 0) 
	    				{
	    					Message msg=new Message();
	    					msg.what=1;
	    					msg.arg1=position;
	    					msg.arg2=duration;
	    					handler.sendMessage(msg);
	    				}
	    			}
	    		}
    		};
    		
    		mTimer=new Timer();
    		mTimer.schedule(mTimerTask, 0, 1000);
    }
    
    public void cancelTimer()
    {
        if (mTimerTask != null) 
        {  
            mTimerTask.cancel();  
            mTimerTask = null;  
        } 
        
        if (mTimer != null) 
		{  
        		mTimer.cancel();  
        		mTimer = null;  
		}  
    }
}